package com.jianggy.javaassist;

import java.lang.reflect.Method;

import javassist.ClassPool;
import javassist.CtClass;

/**
 * Hello world!
 *
 */
public class App {
	public static void main(String[] args) {
//		writeAndRead();
//		invoke();
		defineClass();
	}

	/**
	 * 读写字节码
	 */
	public static void writeAndRead() {
		try {
			// 读字节码
			ClassPool pool = ClassPool.getDefault();
			CtClass ctClass = pool.get("com.jianggy.Test2");
			ctClass.setSuperclass(pool.get("com.jianggy.Test1"));
			// 将字节码写入字节码文件
			ctClass.writeFile();
			//冻结，冻结后不允许修改
			ctClass.defrost();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * 修改类，并通过反射调用
	 */
	public static void invoke() {
		try {
			ClassPool pool = ClassPool.getDefault();
			CtClass ctClass = pool.get("com.jianggy.Test2");
			ctClass.setSuperclass(pool.get("com.jianggy.Test1"));
			
			// 调用父类方法（到真正需要调用的时候还是需要jdk反射，
			// 从这里可以看出两种技术的互补性，需要修改字节码javaassist，需要加载调用jdk）
			Class clazz = ctClass.toClass();
			Object object = clazz.newInstance();
			Method method = clazz.getMethod("test1", String.class);
			method.invoke(object, "调用Test1的父类的方法");
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * 定义一个新类
	 */
	public static void defineClass() {
		try {
			ClassPool pool = ClassPool.getDefault();
			CtClass ctClass = pool.makeClass("com.jianggy.Test3");
			ctClass.writeFile("D:\\codespace\\study\\javacore\\javaassist\\target\\classes\\");
		} catch (Exception e) {
			e.printStackTrace();
		}
		
	}
}
